package domain;

import domain.shop.Company;
import domain.shop.Order;
import org.apache.wicket.authorization.strategies.role.Roles;
import org.hibernate.annotations.Cascade;
import org.hibernate.annotations.CascadeType;
import org.hibernate.search.annotations.Field;
import org.hibernate.search.annotations.Indexed;
import org.jasypt.util.password.PasswordEncryptor;
import org.jasypt.util.password.StrongPasswordEncryptor;

import javax.persistence.*;
import java.io.Serializable;
import java.util.List;


@Entity
@Table(name = "USER")
@NamedQueries({
        @NamedQuery(name = "User.findByLogin",
                query = "from User u where u.login = :login")
})
// @TypeDef(
//        name="encryptedString",
//        typeClass= EncryptedStringType.class,
//        parameters= {
//            @Parameter(name="encryptorRegisteredName", value="strongHibernateStringEncryptor")
//        }
//    )
@Indexed
public class User extends AbstractEntity implements Serializable {
    @Field
    @Column(unique = true, nullable = false)
    private String login = "";
    //@Type(type="encryptedString")

    Roles roles = new Roles();
    @Column(nullable = false)

    private String password = "";
    private String firstName = "";
    private String lastName = "";
    private boolean enabled = false;
    @Column(name = "IS_ADMIN")
    private boolean admin = false;
    @OneToMany(mappedBy = "user", orphanRemoval = true)
    List<Order> orders;
    @OneToOne
    @Cascade(CascadeType.ALL)
    Address address = new Address();
    @OneToOne
    @Cascade(CascadeType.ALL)
    Company company = new Company();

    /**
     * Whether this user has the given role.
     *
     * @param role
     * @return whether this user has the given role
     */
    public boolean hasRole(String role) {
        return this.roles.hasRole(role);
    }

    /**
     * Whether this user has any of the given roles.
     *
     * @param roles set of roles
     * @return whether this user has any of the given roles
     */
    public boolean hasAnyRole(Roles roles) {
        return this.roles.hasAnyRole(roles);
    }

    public Roles getRoles() {
        return this.roles;
    }

    public void setRoles(Roles roles) {
        this.roles = roles;
    }

    @Override
    public String toString() {
        return getLogin() + ", " + getFirstName() + ", " + getLastName() + ", " + getCompanyEmail();
    }

    public Address getAddress() {
        return address;
    }

    public void setAddress(Address address) {
        this.address = address;
    }

    public Company getCompany() {
        return company;
    }

    public void setCompany(Company company) {
        this.company = company;
    }

    public User() {
    }

    public User(String defaultPassword) {
        this.setPassword(defaultPassword);
    }

    public String getFirstName() {
        return firstName;
    }

    public void setFirstName(String firstName) {
        this.firstName = firstName;
    }

    public String getLastName() {
        return lastName;
    }

    public void setLastName(String lastName) {
        this.lastName = lastName;
    }

    public void setStreet(String street) {
        address.setStreet(street);
    }

    public void setPostcode(String postcode) {
        address.setPostcode(postcode);
    }

    public void setMunicipality(String municipality) {
        address.setMunicipality(municipality);
    }

    public void setCountry(String country) {
        address.setCountry(country);
    }

    public String getStreet() {
        return address.getStreet();
    }

    public String getPostcode() {
        return address.getPostcode();
    }

    public String getMunicipality() {
        return address.getMunicipality();
    }

    public String getCountry() {
        return address.getCountry();
    }

    public void setTradingName2(String tradingName2) {
        company.setTradingName2(tradingName2);
    }

    public void setTradingName(String tradingName) {
        company.setTradingName(tradingName);
    }

    public void setTaxID(String taxID) {
        company.setTaxID(taxID);
    }

    public void setPhone(String phone) {
        company.setPhone(phone);
    }

    public void setFax(String fax) {
        company.setFax(fax);
    }

    public void setCompanyID(String companyID) {
        company.setCompanyID(companyID);
    }

    public void setCompanyEmail(String companyEmail) {
        company.setCompanyEmail(companyEmail);
    }

    public void setBankNumber(String bankNumber) {
        company.setBankNumber(bankNumber);
    }

    public String getTradingName2() {
        return company.getTradingName2();
    }

    public String getTradingName() {
        return company.getTradingName();
    }

    public String getTaxID() {
        return company.getTaxID();
    }

    public String getPhone() {
        return company.getPhone();
    }

    public String getFax() {
        return company.getFax();
    }

    public String getCompanyID() {
        return company.getCompanyID();
    }

    public String getCompanyEmail() {
        return company.getCompanyEmail();
    }

    public String getBankNumber() {
        return company.getBankNumber();
    }

    public boolean isAdmin() {
        return admin;
    }

    public void setAdmin(boolean admin) {
        if (admin && !this.roles.hasRole("ADMIN")) {
            this.roles.add("ADMIN");
        } else if (!admin && this.roles.hasRole("ADMIN")) {
            this.roles.remove("ADMIN");
        }
        this.admin = admin;
    }

    public boolean isEnabled() {

        return enabled;
    }

    public void setEnabled(boolean enabled) {
        if (enabled && !this.roles.hasRole("CUSTOMER")) {
            this.roles.add("CUSTOMER");
        } else if (!enabled && this.roles.hasRole("CUSTOMER")) {
            this.roles.remove("CUSTOMER");
        }

        this.enabled = enabled;
    }

    public String getLogin() {
        return login;
    }

    public void setLogin(String login) {
        this.login = login;
    }

    public List<Order> getOrders() {
        return orders;
    }

    public void setOrders(List<Order> orders) {
        this.orders = orders;
    }


    public String getPassword() {
        return password;
    }

    public void setPassword(String password) {

        //TODO predelat aby se to injectovalo ze springu -  je tu problem s inicializaci dat kdyz jeste nebezi wicketapplication
        PasswordEncryptor passwordEncryptor = new StrongPasswordEncryptor();
        this.password = passwordEncryptor.encryptPassword(password);
    }
}
